#
# File: VTKComponent.py
#
# Description: Class definition of the VTK component.
#			  It acts as an interface to VTK.
#
# Author: Jalmar Teeuw and John Donker
# Date created: 12 October 2008
# Date modified: 19 October 2008
#


# import external libraries
import wx
import vtk

from VTKView import *


# class definition
# extends from wxWindow
class VTKComponent(wx.Panel):
	
	# Viewport settings
	VIEW_3D_PER	= 0
	VIEW_3D_ORT	= 1
	VIEW_LEFT	= 2
	VIEW_RIGHT	= 3
	VIEW_TOP	= 4
	VIEW_BOTTOM	= 5
	VIEW_FRONT	= 6
	VIEW_BACK	= 7
	
	
	# constructor
	# -----------
	# dscr:	-
	# req:	-
	# ass:	-
	# ret:	n.a.
	def __init__(self, model, parent, id = -1):
		'''
			Construct a new VTK Component
			Defaults to a single view
			With options to show multiple (4) views
			
			@param model: a reference to the model
			@param parent: the parent to the VTK Component
			@param id: the id for the VTK Component
		'''
		# call super constructor
		wx.Panel.__init__(self, parent, id)
		
		# set window background to black
		#self.SetBackgroundColour(wx.Colour(0,0,0))
		
		# create five VTK views
		self._singleView = VTKView(model, self, id)
		
		self._multiTopLeft = VTKView(model, self, id)
		self._multiTopRight = VTKView(model, self, id)
		self._multiBottomLeft = VTKView(model, self, id)
		self._multiBottomRight = VTKView(model, self, id)
		
		# configure views
		self.SetSingleViewportOptions([ self.VIEW_3D_PER ])
		self.SetMultipleViewportsOptions([ self.VIEW_LEFT, self.VIEW_RIGHT, self.VIEW_FRONT, self.VIEW_3D_PER ])
		self.SetRenderQualityOptions([ True, True, False ])
		
		# start in single view
		#self.SetMultipleViewports()
		self.SetSingleViewport()
		
		# bind events
		#self._topleft.Bind(wx.EVT_SET_FOCUS, self.OnFocus) # Or mouse button (down/up)?
		
	
	#####
	# Configure Layout Procedures
	#####
	
	# configre view for single viewport
	# -----------
	# dscr:	-
	# req:	-
	# ass:	-
	# ret:	n.a.
	def SetSingleViewport(self):
		'''
			Show the single viewport screen
		'''
		# disable multiviews
		self._multiTopLeft.DisableRenderer()
		self._multiTopRight.DisableRenderer()
		self._multiBottomLeft.DisableRenderer()
		self._multiBottomRight.DisableRenderer()
		
		self._multiTopLeft.Hide()
		self._multiTopRight.Hide()
		self._multiBottomLeft.Hide()
		self._multiBottomRight.Hide()
		
		# enable single view
		self._singleView.EnableRenderer()
		self._singleView.Show()
		
		# create new sizer
		bsizer = wx.BoxSizer(wx.VERTICAL)
		
		# add single view to sizer
		#bsizer.Add(self._singleView, -1, wx.EXPAND | wx.ALL, 1)
		bsizer.Add(self._singleView, -1, wx.EXPAND)
		
		# set the new sizer
		self.SetSizer(bsizer)
		
		# update layout
		self.Layout()
	
	
	# configure view for multiple (4) viewports
	# -----------
	# dscr:	-
	# req:	-
	# ass:	-
	# ret:	n.a.
	def SetMultipleViewports(self):
		'''
			Show the multiple viewports screen
		'''
		# disable single view
		self._singleView.DisableRenderer()
		self._singleView.Hide()
		
		# enable multiviews
		self._multiTopLeft.EnableRenderer()
		self._multiTopRight.EnableRenderer()
		self._multiBottomLeft.EnableRenderer()
		self._multiBottomRight.EnableRenderer()
		
		self._multiTopLeft.Show()
		self._multiTopRight.Show()
		self._multiBottomLeft.Show()
		self._multiBottomRight.Show()
		
		# create new sizers
		vsizer = wx.BoxSizer(wx.VERTICAL)
		h1sizer = wx.BoxSizer(wx.HORIZONTAL)
		h2sizer = wx.BoxSizer(wx.HORIZONTAL)
		
		# add multiviews to sizers
		h1sizer.Add(self._multiTopLeft, -1, wx.EXPAND | wx.RIGHT | wx.BOTTOM, 1)
		h1sizer.Add(self._multiTopRight, -1, wx.EXPAND | wx.LEFT | wx.BOTTOM, 1)
		h2sizer.Add(self._multiBottomLeft, -1, wx.EXPAND | wx.RIGHT | wx.TOP, 1)
		h2sizer.Add(self._multiBottomRight, -1, wx.EXPAND | wx.LEFT | wx.TOP, 1)
		
		vsizer.Add(h1sizer, -1, wx.EXPAND)
		vsizer.Add(h2sizer, -1, wx.EXPAND)
		
		# set the new sizer
		self.SetSizer(vsizer)
		
		# update layout
		self.Layout()
	
	
	# change viewport
	# -----------
	# dscr:	-
	# req:	-
	# ass:	-
	# ret:	n.a.
	def _changeView(self, viewport, view):
		'''
			Change the view of a viewport to a certain viw
			
			@param viewport: the viewport to change
			@param view: the view to change the viewport to
			
			@note: this method is private and should not be called by the user
		'''
		if(view == self.VIEW_3D_PER):
			viewport.Set3DPerspectiveView()
		elif(view == self.VIEW_3D_ORT):
			viewport.Set3DOrthogonalView()
		elif(view == self.VIEW_LEFT):
			viewport.SetLeftView()
		elif(view == self.VIEW_RIGHT):
			viewport.SetRightView()
		elif(view == self.VIEW_TOP):
			viewport.SetTopView()
		elif(view == self.VIEW_BOTTOM):
			viewport.SetBottomView()
		elif(view == self.VIEW_FRONT):
			viewport.SetFrontView()
		elif(view == self.VIEW_BACK):
			viewport.SetBackView()
		else:
			viewport.Set3DPerspectiveView() # default
		
	
	# configure single viewport settings
	# -----------
	# dscr:	-
	# req:	-
	# ass:	-
	# ret:	n.a.
	def SetSingleViewportOptions(self, options):
		'''
			Configure the single viewport screen
			
			@param options: a list with the viewport settings
		'''
		# store options
		self._singleViewOptions = options
		
		# change view
		self._changeView(self._singleView, options[0])
		
	
	# get single viewport settings
	# -----------
	# dscr:	-
	# req:	-
	# ass:	-
	# ret:	n.a.
	def GetSingleViewportOptions(self):
		'''
			Return the list of viewport settings
			
			@return: a list of viewport settings
		'''
		return self._singleViewOptions

	
	# configure multiple viewports settings
	# -----------
	# dscr:	-
	# req:	-
	# ass:	-
	# ret:	n.a.
	def SetMultipleViewportsOptions(self, options):
		'''
			Configure the multiple viewports screen
			
			@param options: a list with the viewport settings
		'''
		# store options
		self._multiViewsOptions = options
		
		# change views
		self._changeView(self._multiTopLeft, options[0])
		self._changeView(self._multiTopRight, options[1])
		self._changeView(self._multiBottomLeft, options[2])
		self._changeView(self._multiBottomRight, options[3])
	
	
	# get multiple viewports settings
	# -----------
	# dscr:	-
	# req:	-
	# ass:	-
	# ret:	n.a.
	def GetMultipleViewportsOptions(self):
		'''
			Return the list of viewport settings
			
			@return: a list of viewport settings
		'''
		return self._multiViewsOptions

	
	# configure render quality settings
	# -----------
	# dscr:	-
	# req:	-
	# ass:	-
	# ret:	n.a.
	def SetRenderQualityOptions(self, options):
		'''
			Configure the render quality of the viewports
			
			@param options: a list of render quality options
		'''
		# store options
		self._renderQualityOptions = options
		
		# set double buffering
		self._singleView.SetDoubleBuffering(options[0])
		self._multiTopLeft.SetDoubleBuffering(options[0])
		self._multiTopRight.SetDoubleBuffering(options[0])
		self._multiBottomLeft.SetDoubleBuffering(options[0])
		self._multiBottomRight.SetDoubleBuffering(options[0])
		
		# set depth peeling
		self._singleView.SetDepthPeeling(options[1])
		self._multiTopLeft.SetDepthPeeling(options[1])
		self._multiTopRight.SetDepthPeeling(options[1])
		self._multiBottomLeft.SetDepthPeeling(options[1])
		self._multiBottomRight.SetDepthPeeling(options[1])
		
		# set anti-aliasing
		self._singleView.SetAntiAliasing(options[2])
		self._multiTopLeft.SetAntiAliasing(options[2])
		self._multiTopRight.SetAntiAliasing(options[2])
		self._multiBottomLeft.SetAntiAliasing(options[2])
		self._multiBottomRight.SetAntiAliasing(options[2])
		
	
	# get render quality settings
	# -----------
	# dscr:	-
	# req:	-
	# ass:	-
	# ret:	n.a.
	def GetRenderQualityOptions(self):
		'''
			Return the list of render quality settings
			
			@return: a list of render quality settings
		'''
		return self._renderQualityOptions
		